<?php

namespace Portal\Api;

use Portal\Common\DataApi as Api;
use PhalApi\Exception\BadRequestException;

// use PhalApi\Api;

/**
 *角色接口
 * @author chenwengen 20240420
 */
class Role extends Api
{
    public function getRules()
    {
        return array(
            'tableList' => array(
                'page' => array('name' => 'pageNum', 'type' => 'int', 'default' => 1, 'min' => 1, 'desc' => '页码'),
                'limit' => array('name' => 'pageSize', 'type' => 'int', 'default' => 10, 'min' => 1, 'max' => 100, 'desc' => '每页记录数'),
                'keywords' => array('name' => 'keywords', 'type' => 'string','require' => false, 'desc' => '关键字(角色名称/角色编码)'),
                'searchParams' => array('name' => 'searchParams', 'type' => 'array', 'format' => 'json', 'default' => array(), 'desc' => \PhalApi\T('search params')),
            ),
            'createData' => array(
                'name' => array('name' => 'name', 'require' => true, 'desc' => '角色名称'),
                'code' => array('name' => 'code', 'require' => true, 'on_after_parse' => 'strtoupper', 'desc' => '角色编码'),
                'data_scope' => array('name' => 'dataScope','require' => true, 'type' => 'enum','range' => array(1,2,3,4), 'desc' => '数据权限(1-所有数据 2-部门及子部门数据 3-本部门数据 4-本人数据)'),
                'status' => array('name' => 'status', 'type' => 'enum', 'require' => false,'range' => array('0', '1'),'desc' => '状态'),
                'sort' => array('name' => 'sort', 'type' => 'int', 'require' => false,'min' => 0,'desc' => '排序'),
              ),
            'getData' => array(
                'id' => array('name' => 'id', 'type' => 'int', 'require' => true, 'min' => 1, 'desc' => '角色id'),
            ),
            'deleteData' => array(
                'id' => array('name' => 'id', 'require' => true, 'type' => 'int', 'min' => 1, 'desc' => \PhalApi\T('ID to delete')),
            ),
            'deleteDataIDs' => array(
                'ids' => array('name' => 'ids', 'type' => 'array', 'format' => 'explode', 'seperator' => ',', 'require' => true, 'desc' => \PhalApi\T('ids to delete'))
            ),
            'updateData' => array(
                'id' => array('name' => 'id', 'type' => 'int', 'require' => true, 'min' => 1, 'desc' => 'ID'),
                'name' => array('name' => 'name', 'require' => true, 'desc' => '角色名称'),
                'code' => array('name' => 'code', 'require' => true, 'on_after_parse' => 'strtoupper', 'desc' => '角色编码'),
                'data_scope' => array('name' => 'dataScope','require' => true, 'type' => 'enum','range' => array(1,2,3,4), 'desc' => '数据权限'),
                'status' => array('name' => 'status', 'type' => 'enum', 'require' => false,'range' => array('0', '1'),'desc' => '状态'),
                'sort' => array('name' => 'sort', 'type' => 'int', 'require' => false,'min' => 0,'desc' => '排序'),
                'data' =>  array('name' => 'data', 'type' => 'array', 'format' => 'json', 'require' => false, 'desc' => \PhalApi\T('data to update')),
            ),
          'menuIds' => array(
            'id' => array('name' => 'id', 'type' => 'int', 'require' => true, 'min' => 1, 'desc' => '角色id'),
          ),
          'menus' => array(
              'id' => array('name' => 'id', 'type' => 'int', 'require' => true, 'min' => 1, 'desc' => '角色id'),
            ),
          'status' => array(
              'id' => array('name' => 'roleId', 'type' => 'int', 'require' => true, 'min' => 1, 'desc' => '角色id'),
              'status' =>  array('name' => 'status', 'type' => 'enum', 'require' => true,'range' => array('0', '1'),'desc' => '状态'),

          ),
        );
    }
    protected function getDataModel()
    {
        return new \Portal\Model\Role();
    }
    /**
       * 角色下拉列表视图
       * @desc 获取角色下拉列表视图
       * @return array
    */
    public function options()
    {
        $deptDomain = new \Portal\Domain\Role();
        $returnData = $deptDomain->getOptions();
        return $returnData;
    }
    /**
     * 当在方法使用ingore注解时，则不会显示在接口列表文档上
     * 用于查询接口传入角色id 回调部门id是否存在
     * @ignore
     */
    public static function roleIdList($value, $rule)
    {
        if (!is_array($value)) {
            if (is_numeric($value)) {
                $value = [$value];
            } else {
                $value = json_decode($value, true);
            }
        }
        if (!is_array($value) || empty($value)) {
            throw new BadRequestException('角色id必须为数字');
        }
        $depData = \Portal\Model\Role::notorm()->select('id')->where(['id' => $value])->fetchAll();
        if (is_array($depData) && !empty($depData)) {
            return $value;
        }

        throw new BadRequestException('角色id不存在');
    }

    /**
     * 角色分页列表
     * @desc 角色分页列表
     * @return array    list   列表数据
     * @return int      total   总数量
     */
    public function tableList()
    {
        $this->permissionRequired(["sys:role:query"]);
        $model = $this->getDataModel();

        $searchParams = array();
        foreach ($this->searchParams as $key => $val) {
            if ($val !==  '') {
                $searchParams[$key] = $val;
            }
        }
        // 条件
        $where = !empty($searchParams) ? $searchParams : null;
        $whereParams = array();
        $where = $this->getTableListWhere($where);
        $select = $this->getTableListSelect();
        $order = $this->getTableListOrder();
        $page = $this->page;
        $perpage = $this->limit;
        $total = $model->count($where);
        $items = $total > 0 ? $model->getList($where, $whereParams, $select, $order, $page, $perpage) : array();
        $items = $this->afterTableList($items);

        return $this->returnDataResult(array('total' => $total, 'list' => $items));
    }

    // 列表返回的字段
    protected function getTableListSelect()
    {
        return 'id,name,code,status,sort,create_time,update_time';
    }

    // 列表的默认排序
    protected function getTableListOrder()
    {
        return 'id DESC';
    }

    // 查询条件
    protected function getTableListWhere($where)
    {
        //查看数据权限
        $viewableUsers = $this->dataPermissionRequired("select");
        if ($viewableUsers != 'all' && !empty($viewableUsers)) {
            //获取与角色查询数组的交集
            $where['create_by'] = $viewableUsers;
        }
        $where['code <> ?'] = 'ROOT';
        $where['is_deleted'] = 0;
        if ($this->keywords !== null && trim($this->keywords) != '') {
            $where['code LIKE ? OR name LIKE ?'] = array("%$this->keywords%","%$this->keywords%");
        }
        return $where;
    }

    // 取到列表数据后的加工处理
    protected function afterTableList($items)
    {
        foreach ($items as $key => $item) {
            if (isset($item['create_time'])) {
                $item['createTime'] = date('Y-m-d H:i:s');
                unset($item['create_time']);
            }
            if (isset($item['update_time'])) {
                $item['updateTime'] = date('Y-m-d H:i:s');
                unset($item['update_time']);
            }
            $items[$key] = $item;
        }
        return $items;
    }

    /**
        * 新增角色
        * @desc 新增角色
        * @return int id 新纪录的ID
        * @exception 401 角色名已经存在
        */
    public function createData()
    {
        $this->permissionRequired(["sys:role:add"]);
        $model = $this->getDataModel();

        // $newData = $this->newData;
        $array_keys = array_keys($this->getApiRules());
        $newData = [];
        foreach ($array_keys as $key) {
            if ($this->$key !== null) {
                $newData[$key] = $this->$key;
            }
        }
        $where['name'] = $this->name;
        $where['code'] = $this->code;
        # 检查是否存在未删除的同名或同编码角色
        $checkRole = $this->getDataModel()::notorm()->select('id')->where('(name = :name OR code = :code) AND is_deleted = :isDeleted', [':name' => $this->name,':code' => $this->code,':isDeleted' => 0])->fetchOne();
        if ($checkRole) {
            //用户存在
            throw new BadRequestException('角色名称或编码已存在', 1);
        }
        # 检查是否存在已删除的同名和同编码角色
        $checkDeleteRole = $this->getDataModel()::notorm()->select('id')->where($where)->where(['is_deleted' => 1])->fetchOne();
        if ($checkDeleteRole) {
            # 如果存在，则恢复该角色
            $time = time();
            $updateData['create_time'] = $time;
            $updateData['update_time'] = $time;
            $updateData['is_deleted'] = 0;
            $updateData['create_by'] = \PhalApi\DI()->admin->getId();
            $updateData['update_by'] =  $updateData['create_by'];
            $updateData['sort'] =  $this->sort;
            $updateData['status'] =  $this->status;
            $updateData['data_scope'] =  $this->data_scope;
            $this->getDataModel()::notorm()->where('id', $checkDeleteRole['id'])->update($updateData);
            return $this->returnDataResult(array('id' => intval($checkDeleteRole['id'])));
        }
        # 检查是否存在已删除的同名和同编码角色
        //
        $checkDeleteRole = $this->getDataModel()::notorm()->where('(name = :name OR code = :code) AND is_deleted = :isDeleted', [':name' => $this->name,':code' => $this->code,':isDeleted' => 1])->fetchOne();
        if ($checkDeleteRole) {
            throw new BadRequestException('角色名称或编码已存在（在已删除的角色中)', 1);
        }
        // 检测必传字段
        foreach ($this->createDataRequireKeys() as $key) {
            if (!isset($newData[$key]) || $newData[$key] === '') {
                throw new BadRequestException(\PhalApi\T('{name} require, but miss', array('name' => $key)));
            }
        }
        // 排除字段
        foreach ($this->createDataExcludeKeys() as $key) {
            unset($newData[$key]);
        }

        // 更多初始化的字段数据
        $newData = $this->beforeCreateData($newData);

        if (empty($newData)) {
            throw new BadRequestException(\PhalApi\T('miss post data'));
        }

        $id = 0;
        try {
            $id = $model->insert($newData);
        } catch (\PDOException $ex) {
            throw new BadRequestException(\PhalApi\DI()->debug ? $ex->getMessage() : \PhalApi\T('system error, please contact engeneer'));
        }

        return $this->returnDataResult(array('id' => intval($id)));
    }

    // 必须提供的字段
    protected function createDataRequireKeys()
    {
        return array('name','code');
    }

    // 不允许客户端写入的字段
    protected function createDataExcludeKeys()
    {
        return array('create_time','update_time','is_deleted','update_by','create_by');
    }

    // 创建时更多初始化的数据
    protected function beforeCreateData($newData)
    {
        $time = time();
        $newData['create_time'] = $time;
        $newData['update_time'] = $time;
        $newData['create_by'] = \PhalApi\DI()->admin->getId();
        $newData['update_by'] =  $newData['create_by'];
        return $newData;
    }


    /**
     * 根据ID删除数据
     * @desc 根据单个ID删除数据，也可以调整成根据自定义的条件删除数据
     */
    public function deleteData()
    {
        // $where = array('id' => $this->id);
        $this->ids = [$this->id];
        $this->deleteDataIDs();
        // $model = $this->getDataModel();
        // $rows = !empty($where) ? $model->deleteAll($where) : 0;

        // return $this->returnDataResult(array('deleted_num' => $rows));
    }

    // 删除数据的条件加工
    protected function getDeleteDataWhere($where)
    {
        return $where;
    }

    /**
     * 删除角色
     * @desc 通用数据接口，根据ID批量删除数据
     */
    public function deleteDataIDs()
    {
        $this->permissionRequired(["sys:role:delete"]);
        $model = $this->getDataModel();

        $model = $this->getDataModel();

        if (!is_array($this->ids) || empty($this->ids)) {
            throw new BadRequestException('无效的角色ID', 1);

        }
        $roleDatas = $model::notorm()->select("id,name,create_by")->where(['id' => $this->ids,'is_deleted' => 0])->fetchAll();
        if (!$roleDatas) {
            throw new BadRequestException('无效的角色ID', 1);
        }
        //检查是否有用户关联到该角色
        $roleAdminModel = new \Portal\Model\AdminRole();
        foreach ($roleDatas as $roleData) {
            $checkUserData = $roleAdminModel::notorm()->select('user_id')->where(['role_id' => $roleData['id']])->fetchOne();
            if ($checkUserData) {
                throw new BadRequestException('角色'.$roleData['name'].'已分配用户，请先解除关联后删除', 1);
            }
        }
        # 检查数据权限
        $authorizedRoles = [];
        $unAuthorizedRoles = [];
        foreach ($roleDatas as $roleData) {
            $hasPermission = $this->dataPermissionRequired("delete", $roleData['create_by']);
            if ($hasPermission) {
                $authorizedRoles[] = $roleData['id'];
            } else {
                $unAuthorizedRoles[] = $roleData['name'];
            }
        }
        # 如果有未授权的角色，返回错误信息
        if (!empty($unAuthorizedRoles)) {
            throw new BadRequestException('您没有权限删除以下角色'.implode(',', $unAuthorizedRoles), 3);
        }
        # 执行逻辑删除（将is_deleted设置为1）
        # 获取当前用户作为更新人
        $rows = $this->ids ? $model->updateAll(['id' => $authorizedRoles], ['is_deleted' => 1,'update_by' => \PhalApi\DI()->admin->getId()]) : 0;
        return $this->returnDataResult(array('deleted_num' => $rows));
    }

    /**
     *角色表单数据
     * @desc 角色表单数据
     * @return object|null 数据
     */
    public function getData()
    {
        $this->permissionRequired(["sys:role:select"]);
        $where = array('id' => $this->id);
        $whereParams = array();
        $select = $this->getDataSelect();

        // 前置条件加工
        $where = $this->getGetDataWhere($where);

        $model = $this->getDataModel();
        $data = $model->getData($where, $whereParams, $select);
        $data = $this->afterGetData($data);
        if (!$data) {
            throw new BadRequestException('数据不存在', 4);
        }
        //验证是否有权限更新此角色
        $hasPermission = $this->dataPermissionRequired("select", $data['create_by']);
        if (!$hasPermission) {
            throw new BadRequestException('您没有权限查看此角色', 3);
        }
        return $this->returnDataResult($data);
    }

    // 获取单个数据时需要返回的字段
    protected function getDataSelect()
    {
        return 'id,name,code,sort,status,data_scope,create_by';
    }

    // 前置条件加工
    protected function getGetDataWhere($where)
    {
        $where['is_deleted'] = 0;
        return $where;
    }

    // 取到数据后的加工处理
    protected function afterGetData($data)
    {
        if (isset($data['data_scope'])) {
            $data['dataScope'] = $data['data_scope'];
            unset($data['data_scope']);
        }
        return $data;
    }

    /**
     * 修改角色
     * @desc 修改角色，根据ID更新单条数据
     * @return int|boolean updated_num 更新的数据条数，0表示无更新，1表示更新成功
     * @exception 401 角色名已经存在
     */
    public function updateData()
    {

        $this->permissionRequired(["sys:role:edit"]);
        $model = $this->getDataModel();
        // $updateData = $this->data;
        //获取当前
        $array_keys = array_keys($this->getApiRules());
        $updateData = [];
        foreach ($array_keys as $key) {
            if ($this->$key !== null && $key !== 'data') {
                $updateData[$key] = $this->$key;
            }
        }
        unset($updateData['id']);

        foreach ($this->updateDataRequireKeys() as $key) {
            if (!isset($updateData[$key]) || $updateData[$key] === '') {
                throw new BadRequestException(\PhalApi\T('{name} require, but miss', array('name' => $key)));
            }
        }

        foreach ($this->updateDataExcludeKeys() as $key) {
            unset($updateData[$key]);
        }

        if (empty($updateData)) {
            throw new BadRequestException(\PhalApi\T('miss update data'));
        }

        $updateData = $this->beforeUpdateData($updateData);
        $data = $model::notorm()->select('id,create_by')->where(['id' => $this->id,'is_deleted' => 0])->fetchOne();
        if (!$data) {
            throw new BadRequestException('编辑的权限不存在或者已经删除！');
        }
        //验证是否有权限更新此角色
        $hasPermission = $this->dataPermissionRequired("update", $data['create_by']);
        if (!$hasPermission) {
            throw new BadRequestException('您没有权限编辑此角色', 3);
        }
        try {
            $where = array('id' => $this->id);
            $where = $this->getUpdateDataWhere($where);

            $rows = $model->updateAll($where, $updateData);
            return $this->returnDataResult(array('updated_num' => $rows));
        } catch (\PDOException $ex) {
            throw new BadRequestException(\PhalApi\DI()->debug ? $ex->getMessage() : \PhalApi\T('system error, please contact engeneer'));
        }
    }

    // 更新时必须提供的字段
    protected function updateDataRequireKeys()
    {
        return array('name','code');
    }

    // 更新时不允许更新的字段
    protected function updateDataExcludeKeys()
    {
        return array('create_time','is_deleted','update_by','create_by','update_time');
    }

    // 获取更新数据的条件
    protected function getUpdateDataWhere($where)
    {
        return $where;
    }

    // 在更新数据前的处理
    protected function beforeUpdateData($updateData)
    {
        $updateData['update_time'] = time();
        $where['name'] = $this->name;
        //判断修改后的名称会不会与其他记录重复
        $checkRole = $this->getDataModel()::notorm()->select('id')->where($where)->where('id <> ?', $this->id)->where(['is_deleted' => 0])->fetchOne();
        if ($checkRole) {
            //用户存在
            throw new BadRequestException('角色名称已经存在！', 1);
        }
        $updateData['update_by'] = \PhalApi\DI()->admin->getId();
        return $updateData;
    }
    /**
       *获取角色的菜单ID集合
       * @desc 获取角色的菜单ID集合
       * @return array
    */
    public function menuIds()
    {
        $this->permissionRequired(["sys:role:query"]);
        $returnData = [];
        $id = $this->id;
        //判断传进来角色是否已经删除或者是否禁用
        $this->checkRoleId();
        $roleMenuDomain = new \Portal\Domain\RoleMenu();
        $returnData = $roleMenuDomain->getRoleMenuIds($id);
        return $returnData;
    }
    /**
     *分配菜单(包括按钮权限)给角色
     * @desc 分配菜单(包括按钮权限)给角色
     * @return int
     * @exception 401 菜单id不能为空
     * @exception 401 角色id禁用或者不存在
    */
    public function menus()
    {

        $this->permissionRequired(["sys:role:edit"]);
        $checkRoleData = $this->checkRoleId();

        $postRaw = file_get_contents('php://input');
        if (!empty($postRaw)) {
            $menuIds = json_decode($postRaw, true);
        }
        if (!$menuIds) {
            throw new BadRequestException('菜单id不能为空', 1);
        }
        //处理数据
        $hasPermission = $this->dataPermissionRequired("update", $checkRoleData['create_by']);
        # 验证是否有权限更新此角色
        if (!$hasPermission) {
            throw new BadRequestException('您没有权限分配此角色的菜单权限', 1);
        }
        $roleMenuDomain = new \Portal\Domain\RoleMenu();
        $roleMenuDomain->updateRoleMenus($this->id, $menuIds);
        return 0;
    }
    /**
       *修改角色状态
       * @desc 修改角色状态
       * @return int
       * @exception 403 角色id已经删除
      */
    // public function status()
    // {
    //     //判断角色id对应角色是否存在
    //     $where['is_deleted'] = 1;
    //     $where['id'] = $this->id;
    //     $checkRole = $this->getDataModel()::notorm()->select('id')->where($where)->fetchOne();
    //     if ($checkRole) {
    //         throw new BadRequestException('角色已经删除', 3);
    //     }
    //     $id = $this->id;
    //     $status = $this->status;
    //     $returnData['code'] = 1;
    //     $this->getDataModel()->updateAll(['id' => $id], ['status' => $status]);
    //     return $returnData;
    //     return 0;
    // }
    private function checkRoleId()
    {
        $where['is_deleted = ? OR status = ?'] = array(0,1);
        $where['id'] = $this->id;
        $checkRole = $this->getDataModel()::notorm()->select('id,create_by')->where($where)->fetchOne();
        if (!$checkRole) {
            throw new BadRequestException('角色已经禁用或者删除', 3);
        } else {
            return $checkRole;
        }
    }
}
